package com.zdkj.subway.st.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zdkj.admin.api.entity.SysDictItem;
import com.zdkj.admin.service.SysDictItemService;
import com.zdkj.common.core.exceltools.IExcelExport;
import com.zdkj.common.core.util.R;
import com.zdkj.common.core.util.SpringContextHolder;
import com.zdkj.common.log.annotation.SysLog;
import com.zdkj.common.security.service.PigxUser;
import com.zdkj.common.security.util.ObjectUtils;
import com.zdkj.common.security.util.SecurityUtils;
import com.zdkj.subway.st.dto.in.SwInputExportExcelDTO;
import com.zdkj.subway.st.dto.in.SwTkInputBoxDetailDTO;
import com.zdkj.subway.st.dto.in.SwstInputDetailDTO;
import com.zdkj.subway.st.dto.out.SwStInputDetailDTO;
import com.zdkj.subway.st.dvo.SwStInputDetailExcelDvo;
import com.zdkj.subway.st.entity.SwStInputDetail;
import com.zdkj.subway.st.entity.SwTkInputBoxDetail;
import com.zdkj.subway.st.service.SwTkInputBoxDetailService;
import com.zdkj.subway.st.service.impl.SwStInputDetailServiceImpl;
import com.zdkj.subway.st.util.BarCodeUtils;
import com.zdkj.subway.st.util.DateUtilsSt;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @ProjectName: zdkj
 * @Package: com.zdkj.subway.st.controller
 * @ClassName: SwStInputDetailController
 * @Description:
 * @Author: kangjian
 * @CreateDate: 2020/1/11 9:15
 * @Version: 1.0
 */

@RestController
@AllArgsConstructor
@RequestMapping("/swStInputDetail")
@Api(value = "swStInputDetail", tags = "车票入库管理")
@Slf4j
public class SwStInputDetailController {
    private final SysDictItemService sysDictItemService;
    private final SwStInputDetailServiceImpl SwStInputDetailService;
    private final SwTkInputBoxDetailService swTkInputBoxDetailService;

    /**
     * 入库单分箱头配置
     */
    private final String DICT_IN_TYPE_BOX_NO = "inventory_in_type_box_no";

    /**
     * 入库单已分解标志
     */
    private final String BREAK_FLAG = "1";

    @GetMapping("/{id}")
    public R getById(@PathVariable String id) {
        return R.ok(SwStInputDetailService.getById(id));
    }

    @GetMapping("/page")
    public R<IPage> getDictPage(Page page, SwStInputDetail SwStInputDetail) {
        List<String> dateCondition = SwStInputDetail.getDates1();
        String stockArea = SwStInputDetail.getStockArea();
        if("0".equals(stockArea)){
            SwStInputDetail.setStockArea(null);
        }
        QueryWrapper queryWrapper = Wrappers.query(SwStInputDetail);
        if (ObjectUtil.isNotEmpty(dateCondition)) {
            queryWrapper.between("date_format(in_going_time,'%Y-%m-%d')", dateCondition.get(0), dateCondition.get(1));
        }
        if("0".equals(stockArea)){
            queryWrapper.apply("ISNULL(STOCK_AREA)");
        }
        queryWrapper.orderByDesc("in_going_time");
        return R.ok(SwStInputDetailService.page(page, queryWrapper));
    }

    @SysLog("车票入库保存信息")
    @PostMapping
    @PreAuthorize("@pms.hasPermission('st_input_detail_add')")
    public R save(@Valid @RequestBody SwstInputDetailDTO swstInputDetailDTO) {
        PigxUser user = SecurityUtils.getUser();
        SwStInputDetail swStInputDetail = swstInputDetailDTO.getSwStInputDetail();
        swStInputDetail.setKeeper1code(user.getUserCode());
        swStInputDetail.setKeeper1name(user.getNikeName());
        swStInputDetail.setDataSource("4");//人工添加
        List<SwStInputDetail> swStInputDetails = new ArrayList<>();
        swstInputDetailDTO.getSwStInputDetailList().forEach(item -> {
            SwStInputDetail defaultObj = ObjectUtils.getDefaultObj(SwStInputDetail.class);
            BeanUtils.copyProperties(swStInputDetail, defaultObj);
            BeanUtils.copyProperties(item, defaultObj);
            swStInputDetails.add(defaultObj);
        });
        boolean a = false;
        for(SwStInputDetail item : swStInputDetails){
            a =  SwStInputDetailService.save(item);
        }
        return R.ok(a);
    }

    @SysLog("删除车票入库信息")
    @DeleteMapping("/{id}")
    @PreAuthorize("@pms.hasPermission('st_input_detail_delete')")
    public R removeById(@PathVariable String id) {
        return R.ok(SwStInputDetailService.removeById(id));
    }

    /**
     * 通过id批量删除
     * @param idList id
     * @return R
     */
    @ApiOperation(value = "批量删除库区为空的数据", notes = "批量删除库区为空的数据")
    @SysLog("批量删除库区为空的数据")
    @DeleteMapping("/delBatch")
    public R batchRemoveById(@RequestBody List<Integer> idList) {
        return R.ok(SwStInputDetailService.removeByIds(idList));
    }

    @PutMapping
    @SysLog("修改车票入库信息")
    @PreAuthorize("@pms.hasPermission('st_input_detail_update')")
    public R updateById(@Valid @RequestBody SwStInputDetail SwStInputDetail) {
        PigxUser user = SecurityUtils.getUser();
        SwStInputDetail.setCreatorName(user.getUsername());
        SwStInputDetail.setCreatorId(user.getId());
        R r = SwStInputDetailService.updateInputDetailNew(SwStInputDetail);
        int code = r.getCode();
        String msg = r.getMsg();
        if(code == 1){
            return R.failed(msg);
        }
        return R.ok();
    }

    @PutMapping("/putBatchObj")
    @ApiOperation(value = "车票入库操作和完善信息", notes = "车票入库操作和完善信息")
    public R putBatchObj(@RequestBody SwstInputDetailDTO swstInputDetailDTO) {
        List<Integer> ids = swstInputDetailDTO.getIds();
        SwStInputDetail inputDetailDto = swstInputDetailDTO.getSwStInputDetail();
        boolean a = false;
        //如果ids不为空，就是新增,
        if(CollectionUtil.isNotEmpty(ids)){
            List<SwStInputDetail> swStInputDetailList = SwStInputDetailService.getBaseMapper().selectBatchIds(ids);
            for (SwStInputDetail stInputDetail : swStInputDetailList) {
                stInputDetail.setStockArea(inputDetailDto.getStockArea());
                stInputDetail.setKeeper2name(inputDetailDto.getKeeper2name());
                stInputDetail.setKeeper2code(inputDetailDto.getKeeper2code());
                stInputDetail.setLatestStartTime(inputDetailDto.getLatestStartTime());
                a = SwStInputDetailService.saveOrUpdateDetail(stInputDetail);
            }
        }
        //否则就是完善信息操作,先判断修改前库区是否为空，如果为空，就是新增，否则只修改入库数据
        else {
            //获取修改之前的数据,并判断库区
            SwStInputDetail oldData = SwStInputDetailService.getById(inputDetailDto.getId());
            //是空，新增
            if(StringUtils.isEmpty(oldData.getStockArea())){
                a = SwStInputDetailService.saveOrUpdateDetail(inputDetailDto);
            }else {
                a = SwStInputDetailService.updateById(inputDetailDto);
            }
        }
        return R.ok(a);
    }

    @PutMapping("/applyed")
    @SysLog("入库申请修改")
    @PreAuthorize("@pms.hasPermission('st_input_detail_apply')")
    public R applyed(@Valid @RequestBody List<Integer> ids) {
        return R.ok(SwStInputDetailService.applyedBatch(ids));
    }

    @PutMapping("/approved")
    @SysLog("入库审批修改")
    @PreAuthorize("@pms.hasPermission('st_input_detail_approve')")
    public R approved(@Valid @RequestBody List<Integer> ids) {
        return R.ok(SwStInputDetailService.approvedBatch(ids));
    }

    @GetMapping("/export")
    @SysLog("导出车票入库信息")
    public void exportExcel(SwStInputDetail swStInputDetail, HttpServletResponse response) {
        List<SwStInputDetail> swStIntputDetaillist = SwStInputDetailService.list(Wrappers.query(swStInputDetail));
        IExcelExport excelExport = SpringContextHolder.getBean("commonExcelExport");
        Workbook workbook = excelExport.parse(swStIntputDetaillist);
        try {
            workbook.write(response.getOutputStream());
        } catch (IOException e) {
            log.error("", e);
        }
    }

    /**
     * 通过ids导出文件
     * @param response
     */
    @PostMapping("/exportByIds")
    @SysLog("导出车票入库信息")
    public void exportByIds(@RequestBody List<SwStInputDetailExcelDvo> swStInputDetailExcelDvo, HttpServletResponse response) {
        SwStInputDetailService.exportByIds(swStInputDetailExcelDvo,response);
    }
    /**
     * 通过ids导出文件
     * @param response
     */
    @PostMapping("/exportAll")
    @SysLog("导出车票入库信息")
    public void exportAll(@RequestBody SwInputExportExcelDTO swInputExportExcelDTO , HttpServletResponse response) {
        SwStInputDetailService.exportAll(swInputExportExcelDTO,response);
    }

    /**
     * 新增入库单分箱
     *
     * @param no   入库单号
     * @param list 入库单分箱
     * @return R
     */
    @ApiOperation(value = "新增入库单分箱", notes = "新增入库单分箱")
    @SysLog("新增入库单分箱")
    @PostMapping("/box/{no}")
    @PreAuthorize("@pms.hasPermission('st_sw_tk_input_box_detail_add')")
    public R saveBox(@PathVariable String no, @RequestBody List<SwTkInputBoxDetailDTO> list) {
        SwStInputDetail swStInputDetail = SwStInputDetailService.getOne(Wrappers.<SwStInputDetail>query().lambda()
                .eq(SwStInputDetail::getInstockno, no));
        if (null == swStInputDetail) {
            return R.failed("无记录");
        }
        list.forEach(box -> {
            SwTkInputBoxDetail boxDetail = ObjectUtils.getDefaultObj(SwTkInputBoxDetail.class);
            BeanUtils.copyProperties(box, boxDetail);
            boxDetail.setRefId(swStInputDetail.getId());
            boxDetail.setRefNo(swStInputDetail.getInstockno());
            boxDetail.setBoxNo(createBoxNo(swStInputDetail.getInGoingType()));
            Boolean saveFlag = swTkInputBoxDetailService.save(boxDetail);
            if (!saveFlag) {
                log.error("save error:" + boxDetail.toString());
            } else {
                swStInputDetail.setBreakFlag(BREAK_FLAG);
            }
        });
        SwStInputDetailService.updateById(swStInputDetail);
        return R.ok();
    }


    public String createBoxNo(String type) {
        SysDictItem sysDictItem = sysDictItemService.getOne(Wrappers.<SysDictItem>query().lambda()
                .eq(SysDictItem::getType, DICT_IN_TYPE_BOX_NO)
                .eq(SysDictItem::getValue, type));
        String dateString = DateUtilsSt.getDateFormatter();
        /**
         * 如果为空，没有配置，那就自动生成box的count+1;
         */
        if (null == sysDictItem) {
            return dateString + String.format("%03d", swTkInputBoxDetailService.count() + 1);
        }
        String key = sysDictItem.getLabel() + dateString;
        Integer currentCount = swTkInputBoxDetailService.count(new LambdaQueryWrapper<SwTkInputBoxDetail>()
                .like(SwTkInputBoxDetail::getBoxNo, key));
        return key + String.format("%03d", currentCount + 1);
    }
   /**
     * 按入库单号查找入库单基本信息
     *
     * @param no 入库单号
     * @return R
     */
    @ApiOperation(value = "按入库单号查找入库单基本信息", notes = "按入库单号查找入库单基本信息")
    @SysLog("按入库单号查找入库单基本信息")
    @GetMapping("/instock/input/{no}")
    public R getInputDetailByNo(@PathVariable String no) {
        List list = SwStInputDetailService.list(Wrappers.<SwStInputDetail>query().lambda()
                .eq(SwStInputDetail::getInstockno, no));
		if(list!=null && list.size()>0){
		  return R.ok(list.get(0));
		}
		return R.failed(list,"未获取到对应的入库信息");
		
    }

    /**
     * 按入库单号查找分箱详细记录
     *
     * @param no 入库单号
     * @return R
     */
    @ApiOperation(value = "按入库单号查找分箱详细记录", notes = "按入库单号查找分箱详细记录")
    @SysLog("按入库单号查找分箱详细记录")
    @GetMapping("/box/input/{no}")
    public R getListBoxByInputNo(@PathVariable String no) {
        return R.ok(swTkInputBoxDetailService.list(Wrappers.<SwTkInputBoxDetail>query().lambda()
                .eq(SwTkInputBoxDetail::getRefNo, no)));
    }


    @ApiOperation(value = "根据分箱code查找入库单信息", notes = "根据分箱code查找入库单信息")
    @GetMapping("/box/detail/{boxNo}")
    public R<SwStInputDetailDTO> getInputDetailByBoxNo(@PathVariable String boxNo) {
        SwTkInputBoxDetail box = swTkInputBoxDetailService.getOne(Wrappers.<SwTkInputBoxDetail>query().lambda()
                .eq(SwTkInputBoxDetail::getBoxNo, boxNo));
        if (null == box) {
            return R.failed("无记录");
        }
        SwStInputDetailDTO inputDetailDTO = new SwStInputDetailDTO();

        Integer refId = box.getRefId();
        SwStInputDetail db = SwStInputDetailService.getById(refId);
        BeanUtils.copyProperties(db, inputDetailDTO);
        inputDetailDTO.setSwTkInputBoxDetail(box);
        return R.ok(inputDetailDTO);
    }

    /**
     * 根据分箱ID生成条形码
     *
     * @param id 分箱ID
     * @return R
     * @Description: <p>
     *
     * </p>
     */
    @ApiOperation(value = "根据分箱ID生成条形码", notes = "根据分箱ID生成条形码")
    @GetMapping("/boxs/{id}")
    public R getBarCode(@PathVariable Integer id, HttpServletRequest request, HttpServletResponse response) throws IOException {
        SwTkInputBoxDetail box = swTkInputBoxDetailService.getById(id);
        if (null == box) {
            return R.failed("无记录");
        }

        BufferedImage image = BarCodeUtils.insertWords(BarCodeUtils.getBarCode(box.getBoxNo()), box.getBoxNo());
        ByteArrayOutputStream bs = new ByteArrayOutputStream();
        ImageOutputStream imOut = ImageIO.createImageOutputStream(bs);
        ImageIO.write(image, "jpg", imOut);
        InputStream is = new ByteArrayInputStream(bs.toByteArray());

        // 设置强制下载不打开
        response.setContentType("application/force-download");
        // 设置文件名
        response.addHeader("Content-Disposition",
                "attachment;fileName=" + box.getBoxNo() + ".jpg");
        byte[] buffer = new byte[1024];
        BufferedInputStream bis = null;
        try {
            bis = new BufferedInputStream(is);
            OutputStream os = response.getOutputStream();
            int i = bis.read(buffer);
            while (i != -1) {
                os.write(buffer, 0, i);
                i = bis.read(buffer);
            }
            System.out.println("success");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return null;
    }


}
